/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

package br.ufrj.dcc.comp2.projeto.controles;

import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

import javax.swing.JOptionPane;
import javax.swing.JPanel;

import br.ufrj.dcc.comp2.projeto.internacionalizacao.Ingles;
import br.ufrj.dcc.comp2.projeto.internacionalizacao.InterGeral;
import br.ufrj.dcc.comp2.projeto.modelos.Recordes;
import br.ufrj.dcc.comp2.projeto.modelos.Vetor2D;
import br.ufrj.dcc.comp2.projeto.vistas.JanelaJogo;
import br.ufrj.dcc.comp2.projeto.vistas.MenuJogo;
import br.ufrj.dcc.comp2.projeto.vistas.PainelJogo;
import br.ufrj.dcc.comp2.projeto.vistas.PainelMenuJogo;

/**
 * Classe principal do jogo, faz o setup da janela e gerencia todos os componentes principais do jogo.
 * 
 * @author Bruno(Magoo), Eluan(Acre), Diego(Silvio), Davi.
 *
 */
public class MarteAtaca {

	//Um jogo � a soma de todas as suas partes :P
	private Vetor2D tamanhoTela = new Vetor2D(645, 535);
	private ControlaJogo controlaJogo;
	private CriaComponentes criaComponentes;
	private ControlaInformacoes controlaInformacoes;
	private DetectaColisao detectaColisao;
	private JPanel panel;
	private DesenhaComponentes desenha;
	private ControlaComponentes movComp;
	private JanelaJogo janela; 
	private MenuJogo menu;
	private VerificaGameOver verificaGOver;
	private Recordes recordes;
	private boolean inGame = false;
	private boolean gameOverVariavel = false;
	private boolean endGameFromMenu = false;
	
	//Opcoes de configuracao do jogo:
	private int idioma = 0;
	
	
	
	public static void main(String[] args) {
		@SuppressWarnings("unused")
		MarteAtaca ma = new MarteAtaca();
	}
	
	/**
	 * Inicia o jogo, montando a janela. Alem disso, carrega os recordes.
	 *
	 */
	public MarteAtaca(){
		this.montaJanela();
		this.TelaInicial();
		InterGeral.AlteraIdioma(this, Ingles.ID);
		this.recordes = Recordes.abreRecordes(); 
	}

	private void montaJanela(){
		janela = new JanelaJogo(this);
		janela.setVisible(true);
	}
	
	/**
	 * Inicia um novo jogo.
	 *
	 */
	public void novoJogo(){
		if(this.inGame)
		{
			this.encerraJogo(true);
		}
		
		panel = new PainelJogo(this);
		janela.setPanel(panel);
		
		controlaJogo = new ControlaJogo(tamanhoTela, 6, 10);
		criaComponentes = new CriaComponentes(this);
		controlaInformacoes = new ControlaInformacoes(this);
		detectaColisao = new DetectaColisao(this);
		movComp= new ControlaComponentes(this);
		desenha = new DesenhaComponentes(this);
		janela.addKeyListener(movComp);
		verificaGOver = new VerificaGameOver();
		verificaGOver.ma = this;
		panel.updateUI();
		
		movComp.start();
		desenha.start();	
		verificaGOver.start();
	
		this.inGame = true;
		this.gameOverVariavel = false;
	}

	/**
	 * Marca o jogo como terminado.
	 *
	 * @param fromMenu True se o pedido para encerrar o jogo partiu do menu. Caso contrario, false.
	 */
	public void gameOver(boolean fromMenu){
		this.gameOverVariavel = true;
		if(fromMenu){
			this.endGameFromMenu = true;
		}
	}
	
	/**
	 * Encerra o jogo atual
	 * 
	 * @param novoJogo Apos encerrar o jogo atual, devera iniciar um novo?
	 */
	public void encerraJogo(boolean novoJogo){
		if(!this.inGame){
			return;
		}
		
		
		int confirmacao = 0;
		if(controlaInformacoes.getPontos() > 0 && this.endGameFromMenu == true){
			
			controlaJogo.setPausado(true);
			confirmacao = JOptionPane.showConfirmDialog(janela, InterGeral.retornaStringLocalizada(idioma, InterGeral.DIALOG_CONFIRMACAO_MSG),
					 										InterGeral.retornaStringLocalizada(idioma, InterGeral.DIALOG_CONFIRMACAO_TITLE),
					 										JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null); 
			if(confirmacao == JOptionPane.NO_OPTION){
				controlaJogo.setPausado(false);
				return; //Yoda enviou uma msg ao jogador e ele nao deseja abandonar o jogo :P
			}
		}
		
		
		//RECORDES:
		String nomeDoJogador = "Jogador";
		controlaJogo.setPausado(true);
		if(this.controlaInformacoes.getPontos() > 0 &&  this.recordes.ehRecorde(controlaInformacoes.getPontos())){
			nomeDoJogador = JOptionPane.showInputDialog(janela, InterGeral.retornaStringLocalizada(idioma, InterGeral.DIALOG_RECORDE_JN_MSG),
					InterGeral.retornaStringLocalizada(idioma, InterGeral.DIALOG_RECORDE_JN_TITLE),
					JOptionPane.INFORMATION_MESSAGE);
			controlaInformacoes.fimDoJogo(nomeDoJogador);			
		}
		controlaJogo.setPausado(false);

		//FINALIZA JOGO:
		this.stopThreads();
		if(novoJogo){
			verificaGOver.stopThread();
			while(verificaGOver.isAlive());			
		}
		
		
		janela.removeKeyListener(movComp);
		this.inGame = false;
		this.endGameFromMenu = false;
		
		if(!novoJogo){
			TelaInicial();
		}

		
	}
	
	/**
	 * Monta a tela inicial do jogo.
	 *
	 */
	private void TelaInicial(){
		this.panel = new PainelMenuJogo(this);
		this.janela.setPanel(this.panel);
		panel.updateUI();
		
	}
	
	/**
	 * Para as 2 Threads do jogo em execu��o
	 *
	 */
	private void stopThreads()
	{
		desenha.stopThread();
		while(desenha.isAlive());
		
		movComp.stopThread();
		while(movComp.isAlive());
	}
	
	/**
	 * Mostra o dialog dos recordes.
	 *
	 */
	public void mostraRecordes(){
		boolean jaEstavaPausado = false;
		if(controlaJogo != null){
			jaEstavaPausado = this.controlaJogo.isPausado();
		}
		
		if(inGame && !jaEstavaPausado){
			controlaJogo.setPausado(true);
		}
		
		String sMsgRecordes = "";
		String sNome = "", sMenorNome = "";
		int cur = 0, menor = -1;
		
		Set<String> setNomes = new TreeSet<String>();
		setNomes.addAll(recordes.getRecordes().keySet());
		
		Iterator<String> itNomes = setNomes.iterator();
		while(setNomes.size() > 0)
		{
			while(itNomes.hasNext())
			{
				sNome = itNomes.next();
				cur = recordes.getRecordes().get(sNome);
				if(menor == -1 || cur < menor){
					menor = cur;
					sMenorNome = sNome;
				}
			}
			sMsgRecordes = menor + " - " + sMenorNome + "\n" + sMsgRecordes;
			setNomes.remove(sMenorNome);
			itNomes = setNomes.iterator();
			menor = -1;
		}
		
		if(sMsgRecordes == ""){
			sMsgRecordes = InterGeral.retornaStringLocalizada(idioma, InterGeral.DIALOG_RECORDE_SEMRECORDE);
		}
		
		JOptionPane.showMessageDialog(janela, sMsgRecordes, InterGeral.retornaStringLocalizada(idioma, InterGeral.DIALOG_RECORDE_TITLE), JOptionPane.PLAIN_MESSAGE);
		
		if(inGame && !jaEstavaPausado){
			controlaJogo.setPausado(false);
		}
	}
	
	/**
	 * Mostra dialog dos creditos
	 *
	 */
	public void mostraCreditos(){
		boolean jaEstavaPausado = false;
		if(controlaJogo != null){
			jaEstavaPausado = this.controlaJogo.isPausado();
		}
		
		if(inGame && !jaEstavaPausado){
			controlaJogo.setPausado(true);
		}		

		String sMsg = InterGeral.retornaStringLocalizada(idioma, InterGeral.DIALOG_CREDITOS_MSG);
		String sTitle = InterGeral.retornaStringLocalizada(idioma, InterGeral.DIALOG_CREDITOS_TITLE);
		
		JOptionPane.showMessageDialog(janela, sMsg, sTitle, JOptionPane.PLAIN_MESSAGE);
		
		if(inGame && !jaEstavaPausado){
			controlaJogo.setPausado(false);
		}		
	}
	
	/**
	 * Mostra dialog de ajuda.
	 *
	 */
	public void mostraAjuda(){
		
		boolean jaEstavaPausado = false;
		if(controlaJogo != null){
			jaEstavaPausado = this.controlaJogo.isPausado();
		}
		
		
		if(inGame && !jaEstavaPausado){
			controlaJogo.setPausado(true);
		}		

		String sMsg = InterGeral.retornaStringLocalizada(idioma, InterGeral.DIALOG_AJUDA_MSG);
		String sTitle = InterGeral.retornaStringLocalizada(idioma, InterGeral.DIALOG_AJUDA_TITLE);		
		
		JOptionPane.showMessageDialog(janela, sMsg, sTitle, JOptionPane.PLAIN_MESSAGE);
		
		if(inGame && !jaEstavaPausado){
			controlaJogo.setPausado(false);
		}		
	}

	public ControlaInformacoes getControlaInformacoes() {
		return controlaInformacoes;
	}

	public ControlaJogo getControlaJogo() {
		return controlaJogo;
	}

	public CriaComponentes getCriaComponentes() {
		return criaComponentes;
	}

	public DesenhaComponentes getDesenha() {
		return desenha;
	}

	public DetectaColisao getDetectaColisao() {
		return detectaColisao;
	}

	public boolean isEndGameFromMenu() {
		return endGameFromMenu;
	}

	public boolean isGameOver() {
		return gameOverVariavel;
	}

	public int getIdioma() {
		return idioma;
	}

	public boolean isInGame() {
		return inGame;
	}

	public JanelaJogo getJanela() {
		return janela;
	}

	public MenuJogo getMenu() {
		return menu;
	}

	public ControlaComponentes getMovComp() {
		return movComp;
	}

	public JPanel getPanel() {
		return panel;
	}

	public Recordes getRecordes() {
		return recordes;
	}

	public Vetor2D getTamanhoTela() {
		return tamanhoTela;
	}

	public VerificaGameOver getVerificaGOver() {
		return verificaGOver;
	}

	public void setIdioma(int idioma) {
		this.idioma = idioma;
	}

	public void setMenu(MenuJogo menu) {
		this.menu = menu;
	}	
}
